package leetcode_day._2021._202106._1120;

/**
 * @author yzh
 * @version 1.0
 * @date 2021/6/17 20:02
 * 有效数字
 * 算法：字符串
 * 字符串只包含字母、数字、点号、正负号
 * 根据题意，有效数字必须满足一下几点
 * - 没有 e 或 E，一个小数或整数
 * - 有 e 或 E，该字符之前必须有小数或整数，后面必须是整数
 * - 小数：-4. 或 -4.1 或 -.4, 如果是小数，只有一个点号，就是错的
 * - -、+ 必须出现在数字首位
 * 重点：要记住字符串中肯定是要有数字的
 * -------------------------------------------------------------------
 * 1、先判断字符串中有没有 e(E)
 * 2、如果有，就要分成两部分来判断
 */
public class _17_65 {
    public static void main(String[] args) {
        System.out.println(new _17_65().isNumber("-123.456e789"));
    }

    public boolean isNumber(String s) {
        char[] array = s.toCharArray();
        int index = -1, len = array.length;
        for (int i = 0; i < len; i++) {
            if (array[i] == 'E' || array[i] == 'e') {
                if (index == -1) index = i;
                else return false;
            }
        }
        boolean ans = true;
        if (index == -1) {
            ans &= check(array, 0, len, false);
        } else {
            ans &= check(array, 0, index, false);
            ans &= check(array, index + 1, len, true);
        }
        return ans;

    }

    /**
     *
     * @param array
     * @param start
     * @param end
     * @param mustInteger 为 true 时，判断的字符串一定要为整数，才能返回 true
     * @return
     */
    boolean check(char[] array, int start, int end, boolean mustInteger) {
        // 当 e 为最后一个字符时
        if (start >= end) return false;
        if (array[start] == '+' || array[start] == '-') ++start;
        // hasDot 判断有没有小数点，hasNum 判断有没有数字，不管是小数还是整数，都要有数字
        boolean hasDot = false, hasNum = false;
        for (int i = start; i < end; i++) {
            char c = array[i];
            if (c == '.') {
                // 这一步是最妙的, 如果判断字符是不是为整数, 出现小数点肯定是 false
                // 如果 hasDot 已经为 true 了, 表示之前已经出现过小数点了
                if (mustInteger || hasDot) return false;
                else hasDot = true;
            } else if (c >= '0' && c <= '9') hasNum = true; // 省去了判断是字母的麻烦, 也省去了判断 '.' 这种情况
            else return false;
        }
        return hasNum;
    }

}
